using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
using Object = System.Object;

public class PlayerPrefsDataManager
{
    private static PlayerPrefsDataManager instance = new PlayerPrefsDataManager();

    private PlayerPrefsDataManager()
    {
    }

    public static PlayerPrefsDataManager Instance
    {
        get { return instance; }
    }

    public void SaveData(object data, string keyName)
    {
        Type dataType = data.GetType();
        FieldInfo[] fieldInfos = dataType.GetFields();
        string savekeyName = "";
        for (var i = 0; i < fieldInfos.Length; i++)
        {
            savekeyName = keyName + "_" + dataType.Name + "_" + fieldInfos[i].FieldType.Name + "_" + fieldInfos[i].Name;
            SaveValue(fieldInfos[i].GetValue(data), savekeyName);
        }
        PlayerPrefs.Save();
    }

    private void SaveValue(object getValue, string savekeyName)
    {
        Type valueType = getValue.GetType();
        if (valueType == typeof(int))
        {
            PlayerPrefs.SetInt(savekeyName, (int)getValue);
        }
        else if (valueType == typeof(string))
        {
            PlayerPrefs.SetString(savekeyName, (string)getValue);
        }
        else if (valueType == typeof(float))
        {
            PlayerPrefs.SetFloat(savekeyName, (float)getValue);
        }
        else if (valueType == typeof(bool))
        {
            PlayerPrefs.SetInt(savekeyName, (bool)getValue ? 1 : 0);
        }
        else if (typeof(IList).IsAssignableFrom(valueType))
        {
            //用父类来装载
            IList list = getValue as IList;
            //存储数量
            PlayerPrefs.SetInt(savekeyName, list.Count);
            int index = 0;
            foreach (object obj in list)
            {
                SaveValue(obj, savekeyName + "_" + index);
                index++;
            }
        }
        else if (typeof(IDictionary).IsAssignableFrom(valueType))
        {
            IDictionary dictionary = getValue as IDictionary;
            PlayerPrefs.SetInt(savekeyName, dictionary.Count);
            int index = 0;
            foreach (var key in dictionary.Keys)
            {
                SaveValue(key, savekeyName + "_key_" + index);
                SaveValue(dictionary[key], savekeyName + "_value_" + index);
                index++;
            }
        }
        else
        {
            SaveData(getValue, savekeyName);
        }
    }

    public object LoadData(Type type, string keyName)
    {
        object obj = Activator.CreateInstance(type);
        FieldInfo[] fieldInfos = type.GetFields();
        for (var i = 0; i < fieldInfos.Length; i++)
        {
            string savekeyName = keyName + "_" + type.Name + "_" + fieldInfos[i].FieldType.Name + "_" +
                                 fieldInfos[i].Name;
            fieldInfos[i].SetValue(obj, LoadValue(fieldInfos[i].FieldType, savekeyName));
        }

        return obj;
    }

    private object LoadValue(Type type, string savekeyName)
    {
        if (type == typeof(int))
        {
            return PlayerPrefs.GetInt(savekeyName, 0);
        }
        else if (type == typeof(string))
        {
            return PlayerPrefs.GetString(savekeyName, "");
        }
        else if (type == typeof(float))
        {
            return PlayerPrefs.GetFloat(savekeyName, 0);
        }
        else if (type == typeof(bool))
        {
            return PlayerPrefs.GetInt(savekeyName) == 1 ? true : false;
        }
        else if (typeof(IList).IsAssignableFrom(type))
        {
            int count = PlayerPrefs.GetInt(savekeyName, 0);
            IList list = Activator.CreateInstance(type) as IList;
            for (int i = 0; i < count; i++)
            {
                list.Add(LoadValue(type.GetGenericArguments()[0], savekeyName + "_" + i));
            }

            return list;
        }
        else if (typeof(IDictionary).IsAssignableFrom(type))
        {
            int count = PlayerPrefs.GetInt(savekeyName, 0);
            IDictionary dictionary = Activator.CreateInstance(type) as IDictionary;
            for (int i = 0; i < count; i++)
            {
                Type[] genericArguments = type.GetGenericArguments();
                dictionary.Add(LoadValue(genericArguments[0], savekeyName + "_key_" + i),
                    LoadValue(genericArguments[1], savekeyName + "_value_" + i));
            }

            return dictionary;
        }
        else
        {
            return LoadData(type, savekeyName);
        }

        return null;
    }
}